use std::sync::mpsc::{Receiver, Sender};
use specs::{world::Index, System, Entities, WriteStorage};
use crate::res::{
    position_storage::Position,
    velocity_storage::Velocity,
    overlord_storage::Overlord,
    minions_storage::Minions,
};

pub struct SpawnMessage {
    x: f32,
    y: f32,
    who: Index,
    to: Sender<Index>,
}

impl SpawnMessage {
    pub fn new(x: f32, y: f32, who: Index, to: Sender<Index>) -> Self {
        SpawnMessage {
            x,
            y,
            who,
            to
        }
    }
}

pub struct SpawnSystem {
    rc: Receiver<SpawnMessage>
}

impl SpawnSystem {
    pub fn new(rc: Receiver<SpawnMessage>) -> Self {
        SpawnSystem {
            rc
        }
    }
}

impl<'a> System<'a> for SpawnSystem {
    type SystemData = (
        Entities<'a>,
        WriteStorage<'a, Position>,
        WriteStorage<'a, Velocity>,
        WriteStorage<'a, Overlord>,
        WriteStorage<'a, Minions>,
    );
    
    fn run(&mut self, data: Self::SystemData) {
        let (entities, mut positions, mut velocities, mut overlords, mut minions) = data;

        if let Ok(spawn) = self.rc.try_recv() {
            let entity = entities.create();
            positions.insert(entity, Position{x: spawn.x, y: spawn.y}).unwrap();
            velocities.insert(entity, Velocity{x: 0.0, y: 0.0}).unwrap();
            overlords.insert(entity, Overlord(spawn.who)).unwrap();

            if let Some(minions) = minions.get_mut(entities.entity(spawn.who)) {
                minions.0.push(entity.id());
            }

            spawn.to.send(entity.id()).unwrap();
        }
    }
}